package com.ftar.urgent.audiorecord;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Process;
import android.util.Log;

import java.util.concurrent.atomic.AtomicBoolean;

public class FTAudioRecord {

    private AudioRecord mAudioRecord;
    public static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_STEREO;
    public static int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    public static int SAMPLE_RATE = 8000;
    public static final int BUFFER_SIZE = 1280;
    // AAC, frame/buffer/sec
    public static final int FRAMES_PER_BUFFER = 25;
    // AAC, bytes/frame/channel
    public static final int SAMPLES_PER_FRAME = 5120;
    private AtomicBoolean isRecording;

    public FTAudioRecord() {
        isRecording = new AtomicBoolean(false);
    }

    public int getFrameLen() {
        return AudioRecord.getMinBufferSize(SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_FORMAT);
    }

    private static final int[] AUDIO_SOURCES = new int[]{
            MediaRecorder.AudioSource.VOICE_COMMUNICATION,
            MediaRecorder.AudioSource.MIC,
            MediaRecorder.AudioSource.VOICE_RECOGNITION,
            MediaRecorder.AudioSource.DEFAULT,
            MediaRecorder.AudioSource.CAMCORDER,
    };

    private void init() {
        if (mAudioRecord == null) {
            for (final int source : AUDIO_SOURCES) {
                try {
                    mAudioRecord = new AudioRecord(
                            MediaRecorder.AudioSource.DEFAULT,
                            SAMPLE_RATE,
                            AUDIO_CHANNEL,
                            AUDIO_FORMAT,
                            BUFFER_SIZE);
                    Log.d("audio:", "source:" + source + "  getChannelCount:" + mAudioRecord.getChannelCount());
                    if (mAudioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
                        mAudioRecord = null;
                    }
                } catch (final Exception e) {
                    e.printStackTrace();
                    mAudioRecord = null;
                }
                if (mAudioRecord != null) {
                    break;
                }
            }
        }
    }

    private Runnable recordTask = new Runnable() {
        @Override
        public void run() {
            Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);
            _startRecord();
        }
    };

    private void _startRecord() {
        byte[] data = new byte[SAMPLES_PER_FRAME];
        mAudioRecord.startRecording();
        int readBytes;
        while (isRecording.get()) {
            readBytes = mAudioRecord.read(data, 0, SAMPLES_PER_FRAME);
            mCallback.onDataRecv(data, readBytes);
        }
    }

    private Thread mRecordThread;

    private FTAudioRecordCallback mCallback;

    public void startRecord(FTAudioRecordCallback callback) {
        if (!isRecording.get()) {
            mCallback = callback;
            isRecording.set(true);
            init();
            mRecordThread = new Thread(recordTask);
            if (mAudioRecord == null) {
                return;
            }
            mRecordThread.start();

        }
    }

    public void stopRecord() {
        isRecording.set(false);
        if(mAudioRecord != null){
            mAudioRecord.stop();
            mAudioRecord.release();
            mAudioRecord = null;
        }
        try {
            if (null != mRecordThread) {

                mRecordThread.join();
                mRecordThread = null;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
